package com.ruiyian.web.controller.secondaryaccident;

import com.ruiyian.common.constant.Constants;
import com.ruiyian.common.constant.UserConstants;
import com.ruiyian.common.core.controller.BaseController;
import com.ruiyian.common.core.domain.AjaxResult;
import com.ruiyian.common.core.domain.entity.SysRole;
import com.ruiyian.common.core.domain.entity.SysUser;
import com.ruiyian.common.core.domain.entity.prePlan;
import com.ruiyian.common.core.page.TableDataInfo;
import com.ruiyian.common.utils.SecurityUtils;
import com.ruiyian.common.utils.StringUtils;
import com.ruiyian.common.utils.jfinsUtil.FinsMessage;
import com.ruiyian.common.utils.jfinsUtil.FinsMessageUtils;
import com.ruiyian.netty.nettyclient.NettyStarter;
import com.ruiyian.system.mapper.SecAccidentPrePlanMapper;
import io.netty.channel.ChannelFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/preplan")
public class PrePlanController extends BaseController {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private SecAccidentPrePlanMapper secAccidentPrePlanMapper;

    // 获取预案列表
    @GetMapping("/list")
    public TableDataInfo listPrePlanInfo(prePlan preplan)
    {

        startPage();
        List<prePlan> preplans =  secAccidentPrePlanMapper.selectPrePlanList(preplan);
        return getDataTable(preplans);
    }

    // 根据预案id获取预案信息
    @GetMapping(value = { "/", "/{prePlanUuid}" })
    public TableDataInfo getPrePlanInfoByuuid(@PathVariable(value = "prePlanUuid", required = false) String prePlanUuid)
    {
        startPage();
        String sql = "SELECT spp.id,spp.preplan_uuid as preplanUuid,ts2.server_name as serverName,spp.connection_server_id as serverId, " +
            "spp.connection_point_id as pointId,ts2.host,ts2.port,scp.point_name as pointName, spp.control_value as controlValue, scp.point_type as pointType " +
            "FROM sys_pre_plan_control_point spp LEFT JOIN tb_server_2 ts2 ON spp.connection_server_id=ts2.id " +
            "LEFT JOIN server_control_point scp ON spp.connection_point_id=scp.id " +
            "WHERE spp.preplan_uuid=? AND spp.del_flag=0;";
        Object[] objects = new Object[1];
        objects[0] = prePlanUuid;
        List<Map<String, Object>> prePlanControlPointList =jdbcTemplate.queryForList(sql, objects);
        return getDataTable(prePlanControlPointList);
    }

    // 新增预案
    @PostMapping("/add")
    public AjaxResult add(@RequestBody prePlan preplan){
        System.out.println(preplan);
        // uuid为空，代表是新增
        if(preplan.getPreplanUuid()==null){
            UUID uuid = UUID.randomUUID();
            String insertSql = "INSERT INTO sys_pre_plan (tunnel_id, preplan_uuid, preplan_name, preplan_type, open_flag, create_by, create_time, remark) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
            Object[] objects = new Object[8];
            objects[0] = preplan.getTunnelId();
            objects[1] = uuid.toString();
            objects[2] = preplan.getPreplanName();
            objects[3] = preplan.getPreplanType();
            objects[4] = preplan.getOpenFlag();
            objects[5] = preplan.getCreateBy();
            objects[6] = preplan.getCreateTime();
            objects[7] = preplan.getRemark();
            jdbcTemplate.update(insertSql, objects);
            // 判断点位数据是否存在
            if(preplan.getControlPointList().size()>0){
                String insertControlPointSql = "INSERT INTO sys_pre_plan_control_point (preplan_uuid, connection_server_id, connection_point_id, control_value) VALUES (?, ?, ?, ?)";
                Object[] controlPointObjects = new Object[4];
                for(Map<String, Object> controlPoint:preplan.getControlPointList()){
                    controlPointObjects[0] = uuid.toString();
                    controlPointObjects[1] = controlPoint.get("serverId");
                    controlPointObjects[2] = controlPoint.get("pointId");
                    controlPointObjects[3] = controlPoint.get("controlValue");
                    jdbcTemplate.update(insertControlPointSql, controlPointObjects);
                }
            }
        }
        //不为空，代表是更新
        else {
            Object[] objects = new Object[7];
            String updataSql = "UPDATE sys_pre_plan SET preplan_name=?, preplan_type=?, open_flag=?, create_by=?, create_time=?, remark=? WHERE preplan_uuid=?;";
            objects[0] = preplan.getPreplanName();
            objects[1] = preplan.getPreplanType();
            objects[2] = preplan.getOpenFlag();
            objects[3] = preplan.getCreateBy();
            objects[4] = preplan.getCreateTime();
            objects[5] = preplan.getRemark();
            objects[6] = preplan.getPreplanUuid();
            jdbcTemplate.update(updataSql, objects);
            // 判断点位数据是否存在
            if(preplan.getControlPointList().size()>0){
                // 先删除原先的关联设备信息，然后再插入
                String deleteControlPointSql = "DELETE FROM sys_pre_plan_control_point WHERE preplan_uuid=?";
                Object[] deleteObjects = new Object[1];
                deleteObjects[0] = preplan.getPreplanUuid();
                jdbcTemplate.update(deleteControlPointSql, deleteObjects);
                // 插入控制点位数据
                String insertControlPointSql = "INSERT INTO sys_pre_plan_control_point (preplan_uuid, connection_server_id, connection_point_id, control_value) VALUES (?, ?, ?, ?)";
                Object[] controlPointObjects = new Object[4];
                for(Map<String, Object> controlPoint:preplan.getControlPointList()){
                    controlPointObjects[0] = preplan.getPreplanUuid().toString();
                    controlPointObjects[1] = controlPoint.get("serverId");
                    controlPointObjects[2] = controlPoint.get("pointId");
                    controlPointObjects[3] = controlPoint.get("controlValue");
                    jdbcTemplate.update(insertControlPointSql, controlPointObjects);
                }
            }
            // 不存在就删除预案控制点位数据
            else {
                Object[] prePlanUuid = new Object[1];
                prePlanUuid[0] = preplan.getPreplanUuid();
                String deleteSql = "DELETE FROM sys_pre_plan_control_point WHERE preplan_uuid=?;";
                jdbcTemplate.update(deleteSql, prePlanUuid);
            }
        }

        return AjaxResult.success();
    }

    // 更新预案
    @PostMapping("/updata")
    public AjaxResult updata(@RequestBody prePlan preplan){
        Object[] objects = new Object[7];
        String updataSql = "UPDATE sys_pre_plan SET preplan_name=?, preplan_type=?, open_flag=?, create_by=?, create_time=?, remark=? WHERE preplan_uuid=?;";
        objects[0] = preplan.getPreplanName();
        objects[1] = preplan.getPreplanType();
        objects[2] = preplan.getOpenFlag();
        objects[3] = preplan.getCreateBy();
        objects[4] = preplan.getCreateTime();
        objects[5] = preplan.getRemark();
        objects[6] = preplan.getPreplanUuid();
        jdbcTemplate.update(updataSql, objects);
        // 判断点位数据是否存在
        if(preplan.getControlPointList().size()>0){
            // 先删除原先的关联设备信息，然后再插入
            String deleteControlPointSql = "DELETE FROM sys_pre_plan_control_point WHERE preplan_uuid=?";
            Object[] deleteObjects = new Object[1];
            deleteObjects[0] = preplan.getPreplanUuid();
            jdbcTemplate.update(deleteControlPointSql, deleteObjects);
            // 插入控制点位数据
            String insertControlPointSql = "INSERT INTO sys_pre_plan_control_point (preplan_uuid, connection_server_id, connection_point_id, control_value) VALUES (?, ?, ?, ?)";
            Object[] controlPointObjects = new Object[4];
            for(Map<String, Object> controlPoint:preplan.getControlPointList()){
                controlPointObjects[0] = preplan.getPreplanUuid().toString();
                controlPointObjects[1] = controlPoint.get("serverId");
                controlPointObjects[2] = controlPoint.get("pointId");
                controlPointObjects[3] = controlPoint.get("controlValue");
                jdbcTemplate.update(insertControlPointSql, controlPointObjects);
            }
        }
        // 不存在就删除预案控制点位数据
        else {
            Object[] prePlanUuid = new Object[1];
            prePlanUuid[0] = preplan.getPreplanUuid();
            String deleteSql = "DELETE FROM sys_pre_plan_control_point WHERE preplan_uuid=?;";
            jdbcTemplate.update(deleteSql, prePlanUuid);
        }
        return AjaxResult.success();
    }

    // 删除预案
    @DeleteMapping("/delete/{prePlanUuid}")
    public AjaxResult delete(@PathVariable("prePlanUuid") String prePlanUuid){
        // 删除预案
        Object[] prePlanUuidObject = new Object[1];
        prePlanUuidObject[0] = prePlanUuid;
        String prePlanDeleteSql = "DELETE FROM sys_pre_plan WHERE preplan_uuid=?;";
        jdbcTemplate.update(prePlanDeleteSql, prePlanUuidObject);
        // 同时删除预案控制点位
        String prePlanControlPointDeleteSql = "DELETE FROM sys_pre_plan_control_point WHERE preplan_uuid=?";
        jdbcTemplate.update(prePlanControlPointDeleteSql, prePlanUuidObject);
        return AjaxResult.success();
    }

    // 搜索点位
    @GetMapping("/searchPoint/{pointName}")
    public TableDataInfo listPoint(@PathVariable("pointName") String pointName){
        startPage();
        String searchSql = "";
        List<Map<String, Object>> searchResultPointList;
        if(pointName.equals("all")){
            searchSql = "SELECT scp.id, scp.server_id as serverId, scp.id as pointId, ts2.server_name as serverName, scp.point_name as pointName, scp.point_type as pointType FROM server_control_point scp " +
                "LEFT JOIN tb_server_2 ts2 ON scp.server_id=ts2.id " +
                "WHERE scp.del_flag=0;";
            searchResultPointList =jdbcTemplate.queryForList(searchSql);
        }
        else {
            searchSql = "SELECT scp.id, scp.server_id as serverId, scp.id as pointId, ts2.server_name as serverName, scp.point_name as pointName, scp.point_type as pointType FROM server_control_point scp " +
                "LEFT JOIN tb_server_2 ts2 ON scp.server_id=ts2.id " +
                "WHERE scp.point_name LIKE ? AND scp.del_flag=0;";
            Object[] objects = new Object[1];
            objects[0] = "%"+pointName+"%";
            searchResultPointList =jdbcTemplate.queryForList(searchSql, objects);
        }

        return getDataTable(searchResultPointList);
    }

    // 发送预案
    @GetMapping("/execute/{prePlanUuid}")
    public AjaxResult execute(@PathVariable("prePlanUuid") String prePlanUuid){
        Map<String, String> implementationStatus = new HashMap<String, String>(); // 预案执行情况记录表
        Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
        String searchSql = " SELECT spp.id,spp.preplan_uuid as preplanUuid,ts2.server_name as serverName,ts2.host,ts2.port,scp.point_name as pointName, " +
            "scp.memory_area as memoryArea ,scp.register_address as registerAddress, scp.bits, scp.length, spp.control_value as controlValue FROM sys_pre_plan_control_point spp " +
            " LEFT JOIN tb_server_2 ts2 ON spp.connection_server_id=ts2.id " +
            " LEFT JOIN server_control_point scp ON spp.connection_point_id=scp.id " +
            " WHERE spp.preplan_uuid=? AND spp.del_flag=0;";
        Object[] objects = new Object[1];
        objects[0] = prePlanUuid;
        // 根据preplanuuid搜索点位信息
        List<Map<String, Object>> searchResultPointList =jdbcTemplate.queryForList(searchSql, objects);
        for(Map<String, Object> onePoint:searchResultPointList){
            System.out.println(onePoint);
            // 说明服务正常连接
            if(connectMap.get(onePoint.get("host")+":"+onePoint.get("port"))!=null){
                ChannelFuture channelFuture = connectMap.get(onePoint.get("host")+":"+onePoint.get("port"));
                FinsMessage writeMessage = FinsMessageUtils.createWriteMessage(
                    (int) onePoint.get("memoryArea"),
                    (int) onePoint.get("registerAddress"),
                    (int) onePoint.get("bits"),
                    (int) onePoint.get("controlValue"),
                    onePoint.get("host")+":"+onePoint.get("port"));
                // 将数据发送给plc
                channelFuture.channel().writeAndFlush(writeMessage.toString());
                String deviceName = onePoint.get("serverName") + "-" + onePoint.get("pointName");
                implementationStatus.put(deviceName, "发送成功");
            }
            // 设备未连接
            else {
                String deviceName = onePoint.get("serverName") + "-" + onePoint.get("pointName");
                implementationStatus.put(deviceName, "设备未连接");
            }
        }
        return AjaxResult.success(implementationStatus);
    }

}
